#include "event_app.h"
#include "buzz_board.h"
#include "sound_board.h"
#include "device_parameter.h"

#if _VOICE_PLAY_TYPE_ == _VOICE_PLAY_BUZZ_
/**
 * @brief 获取音量等级
 *
 * @return uint8_t - 音量等级（0~15）
 */
uint8_t BuzzGetVolumeLevel(void);

/**
 * @brief 蜂鸣器输出管脚配置
 *
 */
static void BuzzOutputConfiguration(void);

/**
 * @brief 蜂鸣器输出高电平
 *
 */
static void BuzzSetOutputHighLevel(void);

/**
 * @brief 蜂鸣器输出低电平
 *
 */
static void BuzzSetOutputLowLevel(void);

/**
 * @brief 蜂鸣器任务回调
 *
 */
static uint16_t BuzzTaskCallback(uint8_t TaskId, uint16_t Events);

static uint8_t BuzzTaskHandle = 0;
static BuzzExternalInterfaces_t BuzzExternalInterfaces = {0};

uint8_t BuzzGetVolumeLevel(void)
{
  uint8_t BuzzDutyCycle = 0;
  uint8_t VolumeLevel = GetSystemVolumeLevel();
  if (BuzzGetDoNotDisturbFlag() == true)
  {
    VolumeLevel = BUZZ_MIN_VOLUME_LEVEL;
  }

  if (VolumeLevel >= BUZZ_MIN_VOLUME_LEVEL)
  {
    if (VolumeLevel > BUZZ_MAX_VOLUME_LEVEL)
    {
      VolumeLevel = BUZZ_MAX_VOLUME_LEVEL;
    }

    switch (VolumeLevel)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      BuzzDutyCycle = 5 * VolumeLevel;
      break;

    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
      BuzzDutyCycle = 30 * (VolumeLevel - 5);
      break;

    case 14:
      BuzzDutyCycle = 230;
      break;

    default:
      BuzzDutyCycle = 255;
      break;
    }
  }

  return BuzzDutyCycle;
}

static void BuzzOutputConfiguration(void)
{
#if _BOARD_TYPE_ == _V31_A_BOARD_
  GPIOB_ModeCfg(BASIC_BUZZ_PIN, GPIO_ModeOut_PP_20mA);
  GPIOB_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _V32_A_BOARD_
  GPIOA_ModeCfg(BASIC_BUZZ_PIN, GPIO_ModeOut_PP_20mA);
  GPIOA_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _V32_B_BOARD_
  GPIOB_ModeCfg(BASIC_BUZZ_PIN, GPIO_ModeOut_PP_20mA);
  GPIOB_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _DA01_A_BOARD_
  GPIOB_ModeCfg(BASIC_BUZZ_PIN, GPIO_ModeOut_PP_20mA);
  GPIOB_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _CR01_BU_//ok
  GPIOA_ModeCfg(BASIC_BUZZ_PIN, GPIO_ModeOut_PP_20mA);
  GPIOA_ResetBits(BASIC_BUZZ_PIN);
#endif

  BuzzSetOutputLowLevel();
}

static void BuzzSetOutputHighLevel(void)
{
#if _BUZZER_TYPE_ == _PASSIVE_BUZZER_
  uint8_t BuzzDutyCycle = BuzzGetVolumeLevel();


  if (BuzzDutyCycle > 0)
  {
#if (_BOARD_TYPE_ == _V32_B_BOARD_)//|| (_BOARD_TYPE_ == _CR01_BU_)
    GPIOPinRemap(ENABLE, RB_PIN_PWMX);
#endif

    PWMX_CLKCfg(87);// PWMX_CLKCfg(43);
    PWMX_CycleCfg(PWMX_Cycle_255);
    PWMX_ACTOUT(BASIC_BUZZ_PWM_CHANNEL, (uint8_t)((BuzzDutyCycle / 100.0) * 50), High_Level, ENABLE);
  }

#else
#if _BOARD_TYPE_ == _V31_A_BOARD_
  GPIOB_SetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _V32_A_BOARD_
  GPIOA_SetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _V32_B_BOARD_
  GPIOB_SetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _DA01_A_BOARD_
  GPIOB_SetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _CR01_BU_
  GPIOA_SetBits(BASIC_BUZZ_PIN);
#endif
#endif
}

static void BuzzSetOutputLowLevel(void)
{
#if _BUZZER_TYPE_ == _PASSIVE_BUZZER_
#if (_BOARD_TYPE_ == _V32_B_BOARD_) || (_BOARD_TYPE_ == _DA01_A_BOARD_)
  GPIOPinRemap(DISABLE, RB_PIN_PWMX);
#endif

  PWMX_ACTOUT(BASIC_BUZZ_PWM_CHANNEL, 0, High_Level, DISABLE);
#endif

#if _BOARD_TYPE_ == _V31_A_BOARD_
  GPIOB_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _V32_A_BOARD_
  GPIOA_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _V32_B_BOARD_
  GPIOB_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _DA01_A_BOARD_
  GPIOB_ResetBits(BASIC_BUZZ_PIN);

#elif _BOARD_TYPE_ == _CR01_BU_
  GPIOA_ResetBits(BASIC_BUZZ_PIN);

#endif
}

static uint16_t BuzzTaskCallback(uint8_t TaskId, uint16_t Events)
{
  if (BuzzTaskHandle == TaskId)
  {
    if (Events & BUZZ_SOUND_LISTER)
    {
      if (BuzzExternalInterfaces.SoundEventTask != NULL)
      {
        BuzzExternalInterfaces.SoundEventTask();
      }

      return (Events ^ BUZZ_SOUND_LISTER);
    }
  }

  return 0;
}

void SetBuzzPinLevel(bool PinLevel)
{
  (PinLevel == true) ? BuzzSetOutputHighLevel() : BuzzSetOutputLowLevel();
}

void BuzzSetBusyStatus(bool Status)
{
  EventSetVoicePlayBusyFlagBit(Status);
}

bool BuzzGetDoNotDisturbFlag(void)
{
  return SoundGetDoNotDisturbFlag();
}

void BuzzStopPlaySoundTask(void)
{
  tmos_stop_task(BuzzTaskHandle, BUZZ_SOUND_LISTER);
}

void BuzzDelayedStartPlaySoundTask(uint32_t Ms)
{
  tmos_stop_task(BuzzTaskHandle, BUZZ_SOUND_LISTER);
  tmos_start_task(BuzzTaskHandle, BUZZ_SOUND_LISTER, Ms);
}

void BuzzStartPlaySoundTaskNoWait(void)
{
  tmos_stop_task(BuzzTaskHandle, BUZZ_SOUND_LISTER);
  tmos_set_event(BuzzTaskHandle, BUZZ_SOUND_LISTER);
}

void BuzzBoardInitialisation(BuzzExternalInterfaces_t *pExternalInterfaces)
{
  BuzzExternalInterfaces.SoundEventTask = pExternalInterfaces->SoundEventTask;
  BuzzTaskHandle = TMOS_ProcessEventRegister(BuzzTaskCallback);

  BuzzOutputConfiguration();
}

#endif
